<template>
    <div>
        <el-popover placement="bottom-start" :width="realWidth" trigger="click">
            <el-input
                slot="reference"
                :style="{width:width}"
                v-model="label"
                ref="input"
                readonly
                :id="id"
            ></el-input>
            <div>
                <el-tree
                    class="select-tree"
                    :props="getDefaultProps"
                    :expand-on-click-node="false"
                    @node-click="handleNodeClick"
                    :data="nodes"
                    :style="{height:height+'px'}"
                    @node-expand="handleNodeExpand"
                ></el-tree>
            </div>
        </el-popover>
    </div>
</template>
<script>
export default {
    name: "SelectTree",
    props: {
        width: {
            default: "100%",
            type: String
        },
        height: {
            default: "300",
            type: String
        },
        data: {
            default: null
        },
        value: {
            default: null
        },
        dataValue: {
            default: "id",
            type: String
        },
        dataLabel: {
            default: "label",
            type: String
        },
        dataParentId: {
            default: "pid",
            type: String
        },
        splitChar: {
            default: "",
            type: String
        }
    },
    data() {
        return {
            id: null,
            label: null,
            realWidth: this.width,
            getDefaultProps: {
                children: "children",
                label: "label"
            },
            nodes: []
        };
    },
    created() {
        this.id = "select-tree-" + Math.floor(Math.random() * 100000);
    },
    mounted() {
        if (this.value != null) {
            let v = this.data.find(v => v[this.dataValue] == this.value);
            if (v) {
                this.label = this.getNodeLabel(v);
            }
        }
        let input = document.getElementById(this.id);
        if (input && input.offsetWidth) {
            this.realWidth = input.offsetWidth;
        }
        //element-ui的Tree组件，懒加载时设置leaf=true无效，依然显示折叠图标
        //默认加载一级节点，点击时再展开
        this.nodes = this.getNodesByExpression(
            node => node[this.dataParentId] === 0
        );
    },
    methods: {
        getNodesByExpression(expression) {
            return this.data.filter(expression).map(node => {
                let isLeaf = !this.data.some(
                    n =>
                        n[this.dataParentId] !== 0 &&
                        n[this.dataParentId] == node[this.dataValue]
                );
                let obj = {
                    label: node[this.dataLabel],
                    children: isLeaf ? undefined : [{ placeholder: true }]
                };
                obj[this.dataValue] = node[this.dataValue];
                obj[this.dataParentId] = node[this.dataParentId];
                return obj;
            });
        },
        handleNodeClick(item) {
            this.label = this.getNodeLabel(item);
            this.$emit("input", item[this.dataValue]);
        },
        getNodeLabel(item) {
            if (item[this.dataParentId]) {
                let parent = this.data.find(
                    c => c[this.dataValue] == item[this.dataParentId]
                );
                if (parent) {
                    if (parent[this.dataParentId]) {
                        let grandfather = this.data.find(
                            c => c[this.dataValue] == parent[this.dataParentId]
                        );
                        if (grandfather) {
                            return (
                                grandfather[this.dataLabel] +
                                this.splitChar +
                                parent[this.dataLabel] +
                                this.splitChar +
                                item[this.dataLabel]
                            );
                        }
                    } else {
                        return (
                            parent[this.dataLabel] +
                            this.splitChar +
                            item[this.dataLabel]
                        );
                    }
                }
            }
            return item[this.dataLabel];
        },
        handleNodeExpand(obj, node, vueComponent) {
            if (
                obj.children &&
                obj.children.length === 1 &&
                obj.children[0].placeholder
            ) {
                obj.children = this.getNodesByExpression(
                    v =>
                        v[this.dataParentId] !== 0 &&
                        v[this.dataParentId] == obj[this.dataValue]
                );
            }
        }
    }
};
</script>
<style lang="scss" scoped>
.select-tree {
    width: 100%;
    overflow: auto;
}
</style>